package com.zbc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbc.constants.UserConstant;
import com.zbc.domain.entity.User;
import com.zbc.domain.request.user.UserQueryRequest;
import com.zbc.domain.vo.CaptchaVO;
import com.zbc.domain.vo.LoginUserVO;
import com.zbc.domain.vo.UserVO;
import com.zbc.enums.ErrorCode;
import com.zbc.enums.UserRoleEnum;
import com.zbc.exception.BusinessException;
import com.zbc.mapper.UserMapper;
import com.zbc.service.UserService;
import com.zbc.utils.ThrowUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author fangyu
 * @version v1.0.0
 * @since 2025/9/2 00:09
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    /**
     * 用户注册
     *
     * @param userAccount   用户账号
     * @param userPassword  用户密码
     * @param checkPassword 密码校验
     * @return 新用户id
     */
    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword) {
        // 1. 参数校验
        if (StrUtil.hasBlank(userAccount, userPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        // 2. 账号长度不能小于 6
        if (userAccount.length() < 6) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能小于 6 位");
        }
        // 3. 密码与确认密码长度不能小于 8
        if (userPassword.length() < 8 || checkPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度不能小于 8 位");
        }
        // 4. 密码与确认密码要保持一致
        if (!userPassword.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        // 5. 账号不能重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", userAccount);
        long count = this.getBaseMapper().selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
        }
        // 6. 对密码进行加密(封装一个方法)
        String encryptPassword = this.encryptPassword(userPassword);
        // 7. 插入数据到数据库
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setUserName("忧郁的蘑菇头" + RandomUtil.randomInt(4)); // 默认用户名
        user.setUserRole(UserRoleEnum.USER.getValue());
        boolean saved = this.save(user);
        ThrowUtils.throwIf(!saved, ErrorCode.SYSTEM_ERROR, "保存用户失败");
        // 8. 返回用户 id
        return user.getId();
    }

    /**
     * 用户登录
     *
     * @param userAccount  用户账号
     * @param userPassword 用户密码
     * @param request      存储登录信息到 session
     * @return 登录用户信息(脱敏)
     */
    @Override
    public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        // 1. 参数校验
        if (StrUtil.hasBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数错误");
        }
        ThrowUtils.throwIf(userAccount.length() < 6, ErrorCode.PARAMS_ERROR, "账号长度不能小于 6 位");
        ThrowUtils.throwIf(userPassword.length() < 8, ErrorCode.PARAMS_ERROR, "密码长度不能小于 8 位");
        // 2. 密码加密
        String encryptPassword = this.encryptPassword(userPassword);
        // 3. 查询用户是否存在
        // select * from user where user_account = ? and user_password = ?
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", userAccount).eq("user_password", encryptPassword);
        User user = this.getBaseMapper().selectOne(queryWrapper);
        ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR, "用户账号或密码错误");
        // 4. 保存用户的登录态到 session
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
        // 5. 返回脱敏后的用户信息(封装一个方法)
        return this.LoginUserVO(user);
    }

    /**
     * 获取用户信息(脱敏)
     *
     * @param user 用户信息
     * @return 脱敏后的用户信息
     */
    private LoginUserVO LoginUserVO(User user) {
        ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtil.copyProperties(user, loginUserVO);
        return loginUserVO;
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        // 1. 判断用户是否登录
        User currentUser = (User) request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        ThrowUtils.throwIf(ObjUtil.isNull(currentUser), ErrorCode.NOT_LOGIN_ERROR, "请先登录");
        // 2. 从数据库中查询出当前的登录用户(可以直接返回, 这里是为了保险起见)
        long userId = currentUser.getId();
        ThrowUtils.throwIf(userId <= 0, ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        currentUser = this.getById(userId);
        ThrowUtils.throwIf(ObjUtil.isNull(currentUser), ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        // 3. 返回用户信息
        return currentUser;
    }

    /**
     * 密码加密
     *
     * @param userPassword 密码
     * @return 加密后的密码
     */
    @Override
    public String encryptPassword(String userPassword) {
        ThrowUtils.throwIf(StrUtil.isBlank(userPassword), ErrorCode.PARAMS_ERROR);
        // 密码加密
        return DigestUtils.md5DigestAsHex((UserConstant.SALT + userPassword).getBytes());
    }

    @Override
    public LoginUserVO getLoginUserVO(User user) {
        return null;
    }

    /**
     * 用户注销
     *
     * @param request 用户登录态
     * @return 是否注销成功
     */
    @Override
    public boolean userLogout(HttpServletRequest request) {
        // 1. 判断用户是否登录
        User currentUser = (User) request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        ThrowUtils.throwIf(ObjUtil.isNull(currentUser), ErrorCode.NOT_LOGIN_ERROR, "请先登录");
        // 2. 已经登录, 移除登录态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return true;
    }

    /**
     * 获取用户信息(脱敏)
     *
     * @param user 用户信息
     * @return 脱敏后的用户信息
     */
    @Override
    public UserVO getUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        return userVO;
    }

    /**
     * 获取用户列表(脱敏)
     *
     * @param userList 用户列表
     * @return 脱敏后的用户列表
     */
    @Override
    public List<UserVO> getUserVOList(List<User> userList) {
        if (CollUtil.isEmpty(userList)) {
            return Collections.emptyList();
        }
        return userList.stream().map(this::getUserVO).collect(Collectors.toList());
    }

    /**
     * 分页查询条件封装
     *
     * @param queryRequest 查询参数
     * @return 查询条件
     */
    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest queryRequest) {
        if (queryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        Long id = queryRequest.getId(); // eq
        String userName = queryRequest.getUserName(); // like
        String userAccount = queryRequest.getUserAccount(); // eq
        String userProfile = queryRequest.getUserProfile(); // like
        String userRole = queryRequest.getUserRole(); // eq
        String sortField = queryRequest.getSortField(); // 排序字段
        String sortOrder = queryRequest.getSortOrder(); // 排序顺序
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(StrUtil.isNotBlank(userAccount), "user_account", userAccount);
        queryWrapper.eq(StrUtil.isNotBlank(userRole), "user_role", userRole);
        queryWrapper.like(StrUtil.isNotBlank(userName), "user_name", userName);
        queryWrapper.like(StrUtil.isNotBlank(userProfile), "user_profile", userProfile);
        queryWrapper.orderBy(StrUtil.isNotBlank(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }

    /**
     * 判断是否是管理员
     *
     * @param user 用户
     * @return 判断是否是管理员
     */
    @Override
    public boolean isAdmin(User user) {
        if (ObjUtil.isEmpty(user)) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
    }

    @Override
    public boolean queryUserByEmail(String userEmail) {
        return false;
    }

    @Override
    public User getUserByUserEmail(String userEmail) {
        return null;
    }

    @Override
    public String sendEmailCode(String userEmail) {
        return "";
    }

    @Override
    public CaptchaVO getCaptcha() {
        return null;
    }
}
